﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataMappers;
using ExaminationTT.Model;

namespace ConcreteMappersAndObjects.DomainObjects
{
    public class Exam : DomainObject<int, Exam> , IExam
    {
        protected override Exam Self()
        {
            return this;
        }

        private IValueHolder<int, CUnit> _cunit;
        private List<RoomExam> _rooms;
        private IValueHolder<int, ExamSeason> _examSeason;
        private IEnumerable<RoomExam> _loadedRooms;
        private bool _scheduled;
        private DateTime _examDate;
        private DateTime _examEndDate;

        public Exam() : base()
        {
            _cunit = new ConcreteValueHolder<int, CUnit>();
            _examSeason = new ConcreteValueHolder<int, ExamSeason>();
            _rooms = new List<RoomExam>();
            _scheduled = false;
            
        }
        public Exam(int ID, IValueHolder<int, CUnit> cunit
            , IEnumerable<RoomExam> rooms
            , DateTime examDate
            , DateTime examEndDate
            , IValueHolder<int, ExamSeason> season
            , bool scheduled) : base(ID)
        {
            _cunit = cunit;
            
            _loadedRooms = rooms;
            //_rooms.AddRange(rooms);
            _examDate = new DateTime(examDate.Ticks - (examDate.Ticks % TimeSpan.TicksPerMinute), examDate.Kind);
            _examEndDate = new DateTime(examEndDate.Ticks - (examEndDate.Ticks % TimeSpan.TicksPerMinute), examEndDate.Kind);
            _examSeason = season;
            _scheduled = scheduled;
        }


        public CUnit CUnit
        {
            get { return _cunit.Get(); }
            set
            {
                if (_cunit != value)
                {
                    _cunit.Set(value);
                    MarkDirty();
                }
            }
        }

        public IEnumerable<RoomExam> Rooms
        {
            get 
            {
                if (_rooms == null)
                {
                    _rooms = new List<RoomExam>();
                    _rooms.AddRange(_loadedRooms);
                }
                return _rooms;
            }
            set 
            {
                _rooms = value.ToList();

            }
        }

        public bool AddRoom(Room room)
        {
            if (_rooms == null)
            {
                _rooms = new List<RoomExam>();
                _rooms.AddRange(_loadedRooms);
            }
            if (_rooms.Where(r => r.Room == room).Count() == 0)
            {
                RoomExam re = new RoomExam();
                re.Exam = this;
                re.Room = room;
                _rooms.Add(re);
                return true;
            }
            return false;
        }

        public bool RemoveRoom(Room room)
        {
            if (_rooms == null)
            {
                _rooms = new List<RoomExam>();
                _rooms.AddRange(_loadedRooms);
            }
            foreach (RoomExam re in _rooms.ToArray())
            {
                if (re.Room == room)
                {
                    _rooms.Remove(re);
                    re.Remove();
                    return true;
                }
            }
            return false;
        }

        public DateTime ExamDate
        {
            get { return _examDate; }
            set
            {

                value = new DateTime(value.Ticks - (value.Ticks % TimeSpan.TicksPerMinute), value.Kind);
                if (_examDate != value)
                {
                    _examDate = value;
                    MarkDirty();
                }
            }
        }
        public DateTime ExamEndDate
        {
            get { return _examEndDate; }
            set 
            {
                value = new DateTime(value.Ticks - (value.Ticks % TimeSpan.TicksPerMinute), value.Kind);
                if (_examEndDate != value)
                {
                    if (value.Subtract(ExamDate).Ticks > 0)
                    {
                        _examEndDate = value;
                        MarkDirty();
                    }
                    else
                    {
                        throw new InvalidOperationException("valor tem de ser superior à data de inicio do exame");
                    }
                }
                
            }
        }
        public ExamSeason Season
        {
            get { return _examSeason.Get(); }
            set
            {
                if (_examSeason != value)
                {
                    _examSeason.Set(value);
                    MarkDirty();
                }
            }
        }

        public bool Scheduled
        {
            get { return _scheduled; }
            set
            {
                if (_scheduled != value)
                {
                    _scheduled = value;
                    MarkDirty();
                }
            }
        }

        #region IExam Members

        ICUnit IExam.CUnit
        {
            get { return _cunit.Get(); }
        }

        IEnumerable<IRoomExam> IExam.Rooms
        {
            get 
            {
                if (_rooms == null)
                {
                    _rooms = new List<RoomExam>();
                    _rooms.AddRange(_loadedRooms);
                }
                return _rooms;
            }
        }

        IExamSeason IExam.Season
        {
            get { return _examSeason.Get(); }
        }

        #endregion
    }

  
}
